<?php
/**
 * @name /lib/private/Orphanage.php
 * @author Michael Foss <michael@mikefoss.com>
 * @version 2011.03.26
 * 
 * An orphanage class to manage orphanage.
 */

/**
 * Orphanage class.
 *
 */
class Orphanage {
  /**
   * Orphanage id; unique identifier.
   *
   * @var string
   */
  var $OrphanageId;
  /**
   * Orphanage name.
   *
   * @var string
   */
  var $Name;
  /**
    * The first name of the orphanage's contact person.
    *
    * @var string
    */
  var $ContactFirstName;
  /**
    * The last name of the orphanage's contact person.
    *
    * @var string
    */
  var $ContactLastName;
  /**
    * The phone number of the orphanage's contact person.
    *
    * @var string
    */
  var $ContactPhoneNumber;
  /**
    * The first street address of the orphanage.
    *
    * @var string
    */
  var $Street1;
  /**
    * The second street address of the orphanage;
    * optionally blank, unless Street3 is not.
    *
    * @var string
    */
  var $Street2;
  /**
    * The third street address of the orphanage;
    * optionally blank.
    *
    * @var string
    */
  var $Street3;
  /**
    * The city of the orphanage.
    *
    * @var string
    */
  var $City;
  /**
    * The state or province of the orphanage.
    *
    * @var string
    */
  var $State;
  /**
    * The country of the orphanage.
    *
    * @var string
    */
  var $Country;
  /**
    * The postal code of the orphanage.
    *
    * @var string
    */
  var $PostalCode;
  /**
    * Any administrative notes on the orphanage.
    *
    * @var string
    */
  var $Notes;
  /* Methods:
    "GET":
    Orphanage[] GetOrphanages(int offset, int maxResults)
    bool Exists(int orphanageId)
    string ToString()

    "SCUD":
    bool Load(int orphanageId)
    bool Create(name)
    bool Save()
    static bool Delete(int orphanageId)
    
    Custom:
    static int GetOrphanageIdByOrphanageName(string name)
  */
  
  /**
   * Constructor.
   *
   * @return Orphanage
   */
  function Orphanage() {
    $this->OrphanageId = 0;
    $this->Name = '';
    $this->ContactFirstName = '';
    $this->ContactLastName = '';
    $this->ContactPhoneNumber = '';
    $this->Street1 = '';
    $this->Street2 = '';
    $this->Street3 = '';
    $this->City = '';
    $this->State = '';
    $this->Country = '';
    $this->PostalCode = '';
    $this->Notes = '';
  }
  
  /**
   * Gets a subset of orphanages, sorted by orphanage id,
   * with an optional offset and maximum amount.
   *
   * @param integer
   * @param integer
   * @return Orphanages[]
   */
  function GetOrphanages($offset = 0, $maxResults = 0) {
    $objects = array();
    $db = new DB();
    // Initial query
    $query = "SELECT o.OrphanageId FROM orphanages o ORDER BY o.OrphanageId";
    // Look for max results and offsets
    if ($maxResults && $maxResults * 1 == $maxResults) {
      $query .= " LIMIT $maxResults";
      if ($offset && $offset * 1 == $offset)
        $query .= " OFFSET $offset";
    }
    elseif ($offset && $offset * 1 == $offset)
      $query .= " LIMIT 99999999 OFFSET $offset";
    // Get the ids
    $ids = $db->QueryCol($query);
    // If we have ids, load the objects
    if (is_array($ids))
      foreach ($ids as $id) {
        $objects[count($objects)] = new Orphanage();
        $objects[count($objects) - 1]->Load($id);
      }
    return $objects;
  }
  
  /**
   * Determines if an orphanage exists or not.
   * 
   * @param integer
   * @return boolean
   */
  function Exists($orphanageId) {
    $db = new DB();
    $sql = "SELECT o.OrphanageId FROM orphanages o WHERE o.OrphanageId='" . addslashes($orphanageId) . "' LIMIT 1;";
    return ($db->QueryVal($sql) > 0);
  }

  /**
   * Returns a string representation of the object.
   * 
   * @param string
   * @return string
   */
  function ToString($delimiter = "<br />") {
    $s = "";
    $s .= "OrphanageId: " . $this->OrphanageId . $delimiter;
    $s .= "Name: " . $this->Name . $delimiter;
    $s .= "ContactFirstName: " . $this->ContactFirstName . $delimiter;
    $s .= "ContactLastName: " . $this->ContactLastName . $delimiter;
    $s .= "ContactPhoneNumber: " . $this->ContactPhoneNumber . $delimiter;
    $s .= "Street1: " . $this->Street1 . $delimiter;
    $s .= "Street2: " . $this->Street2 . $delimiter;
    $s .= "Street3: " . $this->Street3 . $delimiter;
    $s .= "City: " . $this->City . $delimiter;
    $s .= "State: " . $this->State . $delimiter;
    $s .= "Country: " . $this->Country . $delimiter;
    $s .= "PostalCode: " . $this->PostalCode . $delimiter;
    $s .= "Notes: " . $this->Notes . $delimiter;
    return $s;
  }

  /**
   * Loads an Orphanage; returns true on success, false on failure.
   *
   * @param integer
   * @return boolean
   */
  function Load($orphanageId) {
    $db = new DB();
    // Prevent SQL injection once to ease coding later
    $orphanageId = addslashes($orphanageId);
    // Select bulk of the data
    $query = <<<HEREDOC
      SELECT
        o.OrphanageId,
        o.OrphanageName AS Name,
        ci.FirstName AS ContactFirstName,
        ci.LastName AS ContactLastName,
        ci.PhoneNumber AS ContactPhoneNumber,
        ci.Street1,
        ci.Street2,
        ci.Street3,
        ci.City,
        ci.StateProvince AS State,
        ci.Country,
        ci.PostalCode,
        o.Notes
      FROM
        orphanages o
      INNER JOIN
        contactinfo ci
      ON
        ci.ContactInfoId=o.ContactInfoId
      WHERE
        o.OrphanageId='{$orphanageId}'
HEREDOC;
    $data = $db->QueryRow($query);
    // If we can't find it, we can't load it
    if (!$data)
      return false;
    // Assign response
    $this->OrphanageId = $data['OrphanageId'];
    $this->Name = $data['Name'];
    $this->ContactFirstName = $data['ContactFirstName'];
    $this->ContactLastName = $data['ContactLastName'];
    $this->ContactPhoneNumber = $data['ContactPhoneNumber'];
    $this->Street1 = $data['Street1'];
    $this->Street2 = $data['Street2'];
    $this->Street3 = $data['Street3'];
    $this->City = $data['City'];
    $this->State = $data['State'];
    $this->Country = $data['Country'];
    $this->PostalCode = $data['PostalCode'];
    $this->Notes = $data['Notes'];

    // If we made it this far, we've loaded the object
    return true;
  }

  /**
   * Creates an orphanage if unique, and returns the orphanage id;
   * returns true on success, false on failure.
   * 
   * @param string
   * @return boolean
   */
  function Create($name) {
    // Make sure orphanage doesn't exist
    if (Orphanage::Exists(Orphanage::GetOrphanageIdByOrphanageName($name)))
      return false;

    $db = new DB();
    // Add a contactinfo record; it'll be empty now, but will be populated
    // when Save() gets called at the end of this method; we'll also need
    // to keep the contactinfo record id for when we add a new orphanage record
    $sql = "INSERT INTO contactinfo VALUES ();";
    $db->Query($sql);
    $sql = "SELECT LAST_INSERT_ID();";
    $contactInfoId = $db->QueryVal($sql);

    // Create a new orphanage record
    $this->Name = trim($name);
    $sql = "INSERT INTO orphanages (OrphanageName, ContactInfoId) VALUES ('" . addslashes($this->Name) . "', '$contactInfoId');";
    $db->Query($sql);
    // Assign the newly-created id
    $sql = "SELECT LAST_INSERT_ID();";
    $this->OrphanageId = $db->QueryVal($sql);

    // Verify the rest of the object data
    // (e.g. is the orphanage name different from other orphanages?);
    // if we can't, remove the data and fail out of the Create
    if (!$this->Save()) {
      Orphanage::Delete($this->OrphanageId);
      $this->OrphanageId = 0;
      $this->Name = '';
      return false;
    }
    else
      return true;
  }
  
  /**
   * Saves a PRE-EXISTING Orphanage; returns true on success, false on failure.
   *
   * @return boolean
   */
  function Save() {
    // "Fix" the data
    $this->Name = trim($this->Name);
    $this->ContactFirstName = trim($this->ContactFirstName);
    $this->ContactLastName = trim($this->ContactLastName);
    $this->ContactPhoneNumber = trim($this->ContactPhoneNumber);
    $this->Street1 = trim($this->Street1);
    $this->Street2 = trim($this->Street2);
    $this->Street3 = trim($this->Street3);
    $this->City = trim($this->City);
    $this->State = trim($this->State);
    $this->Country = trim($this->Country);
    $this->PostalCode = trim($this->PostalCode);
    $this->Notes = trim($this->Notes);

    // Ensure there's a name
    if (!$this->Name)
      return false;
    // Make sure the orphanage exists
    if (!Orphanage::Exists($this->OrphanageId))
      return false;
    // Make sure that any changes to the orphanage name are still unique;
    // the first WHERE clause makes sure we don't accidentally catch the same record
    $sql =
      "SELECT o.OrphanageId " .
      "FROM orphanages o " .
      "WHERE o.OrphanageId<>'" . addslashes($this->OrphanageId) . "' " .
      "AND o.OrphanageName='" . addslashes($this->Name) . "' LIMIT 1;";
    // If we get a result, that means
    // another orphanage has the name already,
    // and we shouldn't save to maintain uniqueness
    $db = new DB();
    if ($db->QueryVal($sql))
      return false;

    // Save the core orphanage data
    $sql =
      "UPDATE orphanages SET " .
        "OrphanageName='" . addslashes($this->Name) . "', " .
        "Notes='" . addslashes($this->Notes) . "' " .
      "WHERE " .
        "OrphanageId='" . addslashes($this->OrphanageId) . "';";
    $db->Query($sql);
    // Save the contact info
    $contactInfoId = $db->QueryVal("SELECT o.ContactInfoId FROM orphanages o WHERE o.OrphanageId='" . addslashes($this->OrphanageId) . "';");
    $sql =
      "UPDATE contactinfo SET " .
        "FirstName='" . addslashes($this->ContactFirstName) . "', " .
        "LastName='" . addslashes($this->ContactLastName) . "', " .
        "PhoneNumber='" . addslashes($this->ContactPhoneNumber) . "', " .
        "Street1='" . addslashes($this->Street1) . "', " .
        "Street2='" . addslashes($this->Street2) . "', " .
        "Street3='" . addslashes($this->Street3) . "', " .
        "City='" . addslashes($this->City) . "', " .
        "StateProvince='" . addslashes($this->State) . "', " .
        "Country='" . addslashes($this->Country) . "', " .
        "PostalCode='" . addslashes($this->PostalCode) . "' " .
      "WHERE " .
        "ContactInfoId='" . addslashes($contactInfoId) . "';";
    $db->Query($sql);
    // Yay! We did it!
    return true;
  }
  
  /**
   * Deletes an orphanage; returns true on success, false on failure.
   *
   * @static
   * @param integer
   * @return boolean
   */
  function Delete($orphanageId) {
    if (!Orphanage::Exists($orphanageId))
      return false;
    $db = new DB();
    $contactInfoId = $db->QueryVal("SELECT o.ContactInfoId FROM orphanages o WHERE o.OrphanageId='" . addslashes($orphanageId) . "'");
    $db->Query("DELETE FROM contactinfo WHERE ContactInfoId='" . addslashes($contactInfoId) . "';");
    $db->Query("DELETE FROM orphanages WHERE OrphanageId='" . addslashes($orphanageId) . "';");
    return true;
  }

  /**
   * Gets the id of an orphanage based on its name;
   * uses a whitespace- and case-insensitive search.
   *
   * @static
   * @param string
   * @return int
   */
  function GetOrphanageIdByOrphanageName($name) {
    $db = new DB();
    return $db->QueryVal("SELECT o.OrphanageId FROM orphanages o WHERE o.OrphanageName='" . addslashes(trim($name)) . "';");
  }
}